package com.ruoyi.collect.sg.manager;


import com.ruoyi.collect.sg.model.CollectorSgDto;
import com.ruoyi.collect.sg.model.FileDto;
import com.ruoyi.collect.sg.service.CollectParser;
import com.ruoyi.common.utils.SnowflakeIdUtils;
import com.ruoyi.tube.domain.SgcdssHistory;
import com.ruoyi.tube.domain.Sgcddy;
import com.ruoyi.tube.domain.Sgcdss;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
public class SgParser extends CollectParser {

    public SgParser(CollectorSgDto mapperDto, final Charset charset) {
        mapper = mapperDto;
        this.charset = charset;
    }

    @Override
    public void parse(final List<FileDto> files) {
        Stream.of((Consumer<List<FileDto>>) this::analyzeCddyFile,
                this::analyzeCdssFile
        ).parallel().forEach(a -> tryAnalyze(a, files));

    }

    protected String getFileNameRegex(final String type) {
        return String.join("", "(\\d+)_", type, "_(\\d{14}).txt");
    }

    protected String getDatum(String[] data, int index) {
        if (data == null || data.length <= index) {
            log.warn("null[{}]: {}", data, index);
            return null;
        }
        String datum = data[index];
        if (!StringUtils.hasText(datum)) {
            log.warn("empty[{}]: {}", data, index);
        }
        return datum.trim();
    }

    protected BigDecimal getDecimal(String[] data, int index) {
        Logger log = LoggerFactory.getLogger(this.getClass());
        if (data == null || data.length <= index || data[index] == null) {
            log.warn("Invalid data or index: data = {}, index = {}", data, index);
            return null;
        }

        String datum = data[index].trim();
        if (!StringUtils.hasText(datum)) {
            log.warn("Empty value at index {}: data = {}", index, data);
            return null;
        }

        try {
            // 将字符串转换为 Decimal
            BigDecimal value = new BigDecimal(datum);
            return value;
        } catch (NumberFormatException e) {
            log.warn("Failed to convert value at index {}: data = {}", index, data, e);
            return null;
        }
    }
    private String getType(final String type) {
        if (type == null) {
            return "其它类型";
        }
        switch (type) {
            case "8001":
                return "CH4";
            case "8002":
                return "CO";
            case "8003":
                return "O2";
            case "8004":
                return "C2H2";
            case "8005":
                return "NO";
            case "8006":
                return "CO2";
            case "8007":
                return "C2H4";
            case "8008":
                return "C2H6";
            case "8009":
                return "N2";
        }
        return "其它类型";
    }
    private String getStatus(final String status) {
        if (status == null) {
            return "";
        }
        switch (status) {
            case "00000000":
                return "正常";
            case "00000001":
                return "超限报警";
            case "00000010":
                return "标校";
            case "00000100":
                return "超量程";
        }
        return "";
    }

    private String getSystemCode(final String status) {
        if (status == null) {
            return "";
        }
        switch (status) {
            case "80":
                return "束管监测系统";
        }
        return "";
    }

    private String getValueType(final String status) {
        if (status == null) {
            return "";
        }
        switch (status) {
            case "MN":
                return "模拟量";
        }
        return "";
    }

    private void analyzeCddyFile(List<FileDto> FileDtos) {
        List<FileDto> FileDto = FileDtos.stream()
                .filter(f -> StringUtils.hasLength(f.getFileName()) && f.getFileName().length() > 18)
                .sorted(Comparator.comparing(f -> f.getFileName().substring(f.getFileName().length() - 18)))
                .collect(Collectors.toList());

        Stream.of((Consumer<List<FileDto>>) this::analyzeSgCddy).parallel().forEach(a -> tryAnalyze(a, FileDto));
    }

    protected void analyzeSgCddy(final List<FileDto> fileInfos) {
        analyze("SGCDDY",fileInfos,this::analyzeSgCddy);
    }

    private void analyzeSgCddy(final List<String> matches, final String content, FileDto fileInfo) {
        long begin = System.currentTimeMillis();
        int count = 0;
        String[] lines = content.split("\\|\\|");
        for (String line : lines) {
            try {
                String[] parts = line.split("~", -1); // 使用 -1 参数确保空字段也被保留
                if (parts.length < 2) {
                    // 如果字段数量不足，跳过该行
                    log.warn("Invalid line: {}", line);
                    continue;
                }
                for (int i = 1; i < parts.length; i++) {
                    // 第一个部分处理
                    String[] mines = parts[0].split(";");
                    String mineCode = getDatum(mines, 0);

                    // 第二个部分使用 ';' 分割
                    String[] data = parts[i].split(";");

                    if (data.length < 9) {
                        log.info("data_invalid: [{}]", line);
                        continue;
                    }
                    long start = System.currentTimeMillis();
                    String pointCode = getDatum(data, 0);
                    String systemCode = getSystemCode(getDatum(data, 1));
                    String pointType = getType(getDatum(data, 2));
                    String pointValueType = getValueType(getDatum(data, 3));
                    String pointValueUnit = getDatum(data, 4);
                    BigDecimal highRange = getDecimal(data, 5);
                    BigDecimal lowRange = getDecimal(data, 6);
                    BigDecimal alarmUpThreashold = getDecimal(data, 7);
                    String pointAreaCode = getDatum(data, 8);
                    String pointArea = getDatum(data, 9);

                    String locationX = getDatum(data, 10);
                    String locationY = getDatum(data, 11);
                    String locationZ = getDatum(data, 12);

                    Sgcddy sgcddy = new Sgcddy();
                    sgcddy.setPointCode(pointCode);
                    sgcddy.setSystemCode(systemCode);
                    sgcddy.setPointType(pointType);
                    sgcddy.setPointValueType(pointValueType);
                    sgcddy.setPointValueUnit(pointValueUnit);
                    sgcddy.setHighRange(highRange);
                    sgcddy.setLowRange(lowRange);
                    sgcddy.setAlarmUpThreashold(alarmUpThreashold);
                    sgcddy.setPointAreaCode(pointAreaCode);
                    sgcddy.setPointArea(pointArea);
                    sgcddy.setLocationX(locationX);
                    sgcddy.setLocationY(locationY);
                    sgcddy.setLocationZ(locationZ);
                    sgcddy.setCreateTime(new Date());
                    Sgcddy sgcddyDb = mapper.getSgcddyService().selectSgcddyBySgcddyId(sgcddy.getPointCode());
                    if (sgcddyDb != null){
                        sgcddy.setSgcddyId(sgcddyDb.getSgcddyId());
                        mapper.getSgcddyService().updateSgcddy(sgcddy);
                    }else {
                        sgcddy.setSgcddyId(String.valueOf(new SnowflakeIdUtils(5,8).nextId()));
                        mapper.getSgcddyService().insertSgcddy(sgcddy);
                    }

                    log.info("cost:" + (System.currentTimeMillis() - start));

                    count++;
                }
            } catch (Exception e) {
                log.warn("", e);
                log.warn("analyze_fail:[{}]", line);
            }
        }
        log.info("end_collect: [{}-{}] [{}]", fileInfo.getFileName(), count, System.currentTimeMillis() - begin);
        fileInfo.setAnalyzed(true);
    }

    private void analyzeCdssFile(List<FileDto> FileDtos) {
        List<FileDto> FileDto = FileDtos.stream()
                .filter(f -> StringUtils.hasLength(f.getFileName()) && f.getFileName().length() > 18)
                .sorted(Comparator.comparing(f -> f.getFileName().substring(f.getFileName().length() - 18)))
                .collect(Collectors.toList());

        Stream.of((Consumer<List<FileDto>>) this::analyzeSgCdss).parallel().forEach(a -> tryAnalyze(a, FileDto));
    }

    protected void analyzeSgCdss(final List<FileDto> fileInfos) {
        analyze("SGCDSS", fileInfos, this::analyzeSgCdss);
    }

    private void analyzeSgCdss(final List<String> matches, final String content, FileDto fileInfo) {
        long begin = System.currentTimeMillis();
        int count = 0;

        String[] lines = content.split("\\|\\|");
        for (String line : lines) {
            try {
                String[] parts = line.split("~", -1); // 使用 -1 参数确保空字段也被保留
                if (parts.length < 2) {
                    // 如果字段数量不足，跳过该行
                    log.warn("Invalid line: {}", line);
                    continue;
                }
                for (int i = 1; i < parts.length; i++) {
                    // 第一个部分处理
                    String[] mines = parts[0].split(";");
                    String mineCode = getDatum(mines, 0);

                    // 第二个部分使用 ';' 分割
                    String[] data = parts[i].split(";");
                    if (data.length < 7) {
                        log.info("data_invalid: [{}]", line);
                        continue;
                    }
                    long start = System.currentTimeMillis();
                    String pointCode = getDatum(data, 0);
                    //String pointType = getType(getDatum(data, 1));
                    String pointType = getDatum(data, 1);
                    String pointAreaCode = getDatum(data, 2);
                    String pointArea = getDatum(data, 3);
                    BigDecimal pointValue = getDecimal(data, 4);
                    String pointValueUnit = getDatum(data, 5);
                    String status = getDatum(data, 6);
                    Date dataTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(getDatum(data, 7));
                    Sgcdss sgcdss = new Sgcdss();
                    sgcdss.setPointCode(pointCode);
                    sgcdss.setPointType(pointType);
                    sgcdss.setPointAreaCode(pointAreaCode);
                    sgcdss.setPointArea(pointArea);
                    sgcdss.setPointValue(pointValue);
                    sgcdss.setPointValueUnit(pointValueUnit);
                    sgcdss.setUpdateTime(dataTime);
                    if (status != null) {
                        String s = Integer.toBinaryString(Integer.parseInt(status));
                        while (s.length() < 8) {
                            s = "0" + s;
                        }
                        String pointStatus = getStatus(s);
                        sgcdss.setPointStatus(pointStatus);
                    }
                    Sgcdss sgcdssDb = mapper.getSgcdssService().selectSgcdssByPointCode(pointCode);
                    if (sgcdssDb != null){
                        sgcdss.setSgcdssId(sgcdssDb.getSgcdssId());
                        mapper.getSgcdssService().updateSgcdss(sgcdss);
                    }else {
                        sgcdss.setSgcdssId(String.valueOf(new SnowflakeIdUtils(5,8).nextId()));
                        mapper.getSgcdssService().insertSgcdss(sgcdss);
                    }
                    SgcdssHistory sgcdssHistory = new SgcdssHistory();
                    BeanUtils.copyProperties(sgcdss,sgcdssHistory);
                    sgcdssHistory.setSgcdssId(String.valueOf(new SnowflakeIdUtils(5,8).nextId()));
                    mapper.getSgcdssHistoryService().insertSgcdssHistory(sgcdssHistory);
                    log.info("cost:" + (System.currentTimeMillis() - start));

                    count++;
                }
            } catch (Exception e) {
                log.warn("", e);
                log.warn("analyze_fail:[{}]", line);
            }
        }
        log.info("end_collect: [{}-{}] [{}]", fileInfo.getFileName(), count, System.currentTimeMillis() - begin);
        fileInfo.setAnalyzed(true);
    }
}
